/* This file is part of FObject.
 *
 * FObject is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * FObject is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with FObject.  If not, see <http://www.gnu.org/licenses/>.
 */

#import <Prelude.h>
#import <Foundation/NSString.h>

@implementation Prelude

+ (Bool*) boxBool: (BOOL) b
{
  return [[Bool alloc] initWithBool: b];
}

+ (Int*) boxInt: (int) n
{
  return [[Int alloc] initWithInt: n];
}

+ (Float*) boxFloat: (float) f
{
  return [[Float alloc] initWithFloat: f];
}

+ (String*) boxString: (NSString*) s
{
  return [[String alloc] initWithString: s];
}

+ (Int*) addInt: (Int*) m: (Int*) n
{
  return [[Int alloc] initWithInt: [m value] + [n value]];
}

+ (Int*) subInt: (Int*) m: (Int*) n
{
  return [[Int alloc] initWithInt: [m value] - [n value]];
}

+ (Int*) mulInt: (Int*) m: (Int*) n
{
  return [[Int alloc] initWithInt: [m value] * [n value]];
}

+ (Int*) divInt: (Int*) m: (Int*) n
{
  return [[Int alloc] initWithInt: [m value] / [n value]];
}

+ (Int*) modInt: (Int*) m: (Int*) n
{
  return [[Int alloc] initWithInt: [m value] % [n value]];
}

+ (Int*) negInt: (Int*) n
{
  return [[Int alloc] initWithInt: -[n value]];
}

+ (String*) stringOfInt: (Int*) n
{
  return [[String alloc] initWithString: [n toString]];
}

+ (Int*) intOfFloat: (Float*) f
{
  return [[Int alloc] initWithInt: (int) [f value]];
}

+ (Int*) intOfString: (String*) s
{
  return [[Int alloc] initWithInt: [[s value] intValue]];
}

+ (Float*) addFloat: (Float*) m: (Float*) n
{
  return [[Float alloc] initWithFloat: [m value] + [n value]];
}

+ (Float*) subFloat: (Float*) m: (Float*) n
{
  return [[Float alloc] initWithFloat: [m value] - [n value]];
}

+ (Float*) mulFloat: (Float*) m: (Float*) n
{
  return [[Float alloc] initWithFloat: [m value] * [n value]];
}

+ (Float*) divFloat: (Float*) m: (Float*) n
{
  return [[Float alloc] initWithFloat: [m value] / [n value]];
}

+ (Float*) negFloat: (Float*) n
{
  return [[Float alloc] initWithFloat: -[n value]];
}

+ (String*) stringOfFloat: (Float*) n
{
  return [[String alloc] initWithString: [n toString]];
}

+ (Float*) floatOfString: (String*) s
{
  return [[Float alloc] initWithFloat: [[s value] floatValue]];
}

+ (Float*) floatOfInt: (Int*) n
{
  return [[Float alloc] initWithFloat: (float) [n value]];
}

+ (Bool*) andBool: (Bool*) b: (Bool*) c
{
  return [[Bool alloc] initWithBool: [b value] && [c value]];
}

+ (Bool*) orBool: (Bool*) b: (Bool*) c
{
  return [[Bool alloc] initWithBool: [b value] || [c value]];
}

+ (Bool*) notBool: (Bool*) b
{
  return [[Bool alloc] initWithBool: ![b value]];
}

+ (String*) concatString: (String*) s: (String*) t
{
  return [[String alloc] initWithString: [[s value] stringByAppendingString: [t value]]];
}

+ (Value*) null
{
  return nil;
}

+ (Bool*) isNull: (Value*) v
{
  return [Prelude boxBool: (v == nil)];
}

+ (Pair*) cons: (Value*) v: (Value*) w
{
  return [[Pair alloc] initWith: v: w];
}

+ (Value*) first: (Pair*) v
{
  return [v first];
}

+ (Value*) second: (Pair*) v
{
  return [v second];
}

@end
